const { Service } = require('egg');
const { tableToList } = require('../utils/tools');

/**
 * 根据输入的成绩字符串判断其状态。
 * @param {string} str 表示成绩的字符串，可以是数字或者文字。
 * @return {Array} 返回一个包含两个元素的数组。第一个元素是输入的成绩字符串，第二个元素是成绩的状态，
 *                  如果成绩是数字，则状态为'已获'（及格）或'已开未获'（不及格）；如果成绩是文字，则状态为'已获'（及格）或'已开未获'（不及格）。
 */
const gradeStatus = str => {
  if (/^\d+$/.test(str)) { // 如果输入的是数字
    return [ str, (Number(str) >= 60) ? '已获' : '已开未获' ]; // 判断数字是否及格，及格则返回'已获'，否则返回'已开未获'
  }
  return [ str, str === '不及格' ? '已开未获' : '已获' ]; // 如果输入的是文字，判断是否为'不及格'，是则返回'已开未获'，否则返回'已获'
};

/**
 * 根据入学年份、开设学期（1、2、3、...）获取学期
 * @param {number} year 年份
 * @param {number} sub 开设学期（1、2、3、...）
 * @return {string} 学期
 */
const getTerm = (year, sub) => {
  // year不是数字返回空
  if (isNaN(sub)) return '';
  const t1 = Number(year) + Math.floor((Number(sub) - 1) / 2);
  const t2 = Number(year) + Math.floor((Number(sub) - 1) / 2) + 1;
  return `${t1}-${t2}-${Number(sub) % 2 === 0 ? '2' : '1'}`;
};

module.exports = class CreditService extends Service {
  /**
   * * 学分修读情况
   * @return {Array} *
   */
  async table() {
    const Cookie = this.ctx.state.Cookie;

    const planUrl = `${this.ctx.state.baseUrl}/jsxsd/pyfa/topyfamx`; // 培养方案

    const scheduletUrl = `${this.ctx.state.baseUrl}/jsxsd/xxwcqk/xxwcqk_byxfqkcx.do`; // 学习过程情况

    const gradeUrl = `${this.ctx.state.baseUrl}/jsxsd/kscj/cjcx_list`; // 成绩

    const P1 = this.ctx.curl(planUrl, {
      method: 'GET',
      headers: {
        Cookie,
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      timeout: 10000,
    });
    const P2 = this.ctx.curl(scheduletUrl, {
      method: 'GET',
      headers: {
        Cookie,
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      timeout: 10000,
    });
    const P3 = this.ctx.curl(gradeUrl, {
      method: 'POST',
      data: {
        kksj: '',
        kcxz: '',
        kcmc: '',
        xsfs: 'all',
      },
      headers: {
        Cookie,
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      timeout: 10000,
    });

    const [ R1, R2, R3 ] = await Promise.all([ P1, P2, P3 ]);

    if (R1.status === 200 && R2.status === 200 && R3.status === 200) {
      try {
        /* 获取课程应修分数 */
        const needTable = tableToList(R1.data.toString(), '#dataList tbody tr:nth-child(2) table');
        const need = { 通识教育选修课: '0', 专业选修课: '0' }; // 课程类别-应修学分
        for (let i = 1; i < needTable.length - 1; i++) {
          if (needTable[i][0].includes('合计') || needTable[i][0].includes('类别')) { continue; }
          else if (needTable[i][1] === '选修') need[needTable[i - 1][0].replace('课', '') + '选修课'] = needTable[i][3];
          else if (needTable[i + 1][0] === '') need[needTable[i][0].replace('课', '') + needTable[i][1] + '课'] = needTable[i][3];
          else if (needTable[i][0].includes('实践')) need[needTable[i][0]] = needTable[i][2];
          else need[needTable[i][0]] = needTable[i][3];
        }
        /* end */

        /* 从成绩页面获取修读情况 */
        const temD = {};
        const gradeTable = tableToList(R3.data.toString(), '#dataList');
        const saveName = [];
        gradeTable.forEach((item, idx) => {
          if (idx === 0 || !item[10] || item[3] === '创新创业、社会实践活动') return true; // 去掉课程性质为空课程
          const [ grade, status ] = gradeStatus(item[4]);

          if (saveName.includes(item[3])) { // 重复课程取最高分
            if (status === '已获') {
              temD[item[3]][0] = item[1];
              temD[item[3]][1] = grade;
              temD[item[3]][4] = status;
            }
            return true;
          }

          temD[item[3]] = [ item[1], item[4], item[5], item[10], status ];
          saveName.push(item[3]);
        });
        // console.log('gradeTable', gradeTable);
        /* end */

        /*
          1. 从培养计划中获取课程名称及课程性质，用户得到修读中课程的课程性质
          2. 统计非选修课程需要修读的学分
        */
        const nameType = {};
        let type = '';
        const tableList2 = tableToList(R1.data.toString(), '#mxh');
        tableList2.forEach((item, idx) => {
          if (idx < 2) return true;
          if (item[0] === '合计') return false;
          if (item[0] === '小计') {
            if (!type.includes('专业') || !type.includes('选修')) {
              if (!need[type]) need[type] = item[5];
            }
            type = '';
            return true;
          }
          if (type === '') type = item[0];
          if (!(item[3] in temD)) {
            temD[item[3]] = [ getTerm(this.ctx.data.sid.slice(0, 4), Number(item[item.length - 1])), '', item[5], type, '' ];
          }
          nameType[item[3]] = type;
        });
        // console.log('nameType', nameType);
        // console.log('temD', temD);
        /* end */

        /* 从完成情况中获取修读中的课程数据，并得到其对应的课程性质 */
        const resultTable1 = tableToList(R2.data.toString(), '#t1');
        const resultTable2 = tableToList(R2.data.toString(), '#t3');

        resultTable1.forEach(e => {
          if (e[6] === '修读中') temD[e[3]] = [ e[1], e[5], e[4], nameType[e[3]], e[6] ];
        });
        resultTable2.forEach(e => {
          if (e[6] === '修读中') temD[e[3]] = [ e[1], e[5], e[4], '通识教育选修课', e[6] ];
        });
        /* end */
        /* 数据准备完成，开始构造最终数据 */
        const saveType = []; // 课程性质
        const result = [];
        for (const key in temD) {
          const type = temD[key][3];
          const index = saveType.indexOf(type);
          if (index === -1) {
            saveType.push(type);
            result.push({
              category: type,
              details: [{
                N: key,
                T: temD[key][0],
                G: temD[key][1],
                C: temD[key][2],
                S: temD[key][4],
              }],
              need: need[type],
              has: temD[key][4] === '已获' ? temD[key][2] : '0',
            });
          } else {
            result[index].details.push({
              N: key,
              T: temD[key][0],
              G: temD[key][1],
              C: temD[key][2],
              S: temD[key][4],
            });
            if (temD[key][4] === '已获') result[index].has = `${Number(temD[key][2]) + Number(result[index].has)}`;
          }
        }
        /* 按学期排序 */
        for (const i of result) {
          i.details.sort((a, b) => {
            if (a.T < b.T) return -1;
            if (a.T > b.T) return 1;
            return 0;
          });
        }
        return result;
      } catch (err) {
        throw err;
      }
    }
    return [];
  }

  /**
   * * 创新学分、素拓分、第二课堂分
   * @return {Array} *
   */
  async extra() {
    const Cookie = this.ctx.state.Cookie;
    const apiUrl = `${this.ctx.state.baseUrl}/jsxsd/pyfa/cxxf_query`;
    const res = await this.ctx.curl(apiUrl, {
      method: 'GET',
      headers: {
        Cookie,
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      timeout: 10000,
    });

    const header = [ '学期', '项目名称', '学分', '编号', '类型', '备注' ]; // 列名称
    if (res.status === 200) {
      try {
        const tableList = tableToList(res.data.toString(), '#dataList');
        /* [ '序号', '学年学期', '项目编号', '学号', '姓名', '学分', '学分类型', '备注' ]; */

        const columnNeed = [ 1, 3, 6, 2, 7, 8 ]; // 需要提取的列序号
        if (tableList.length === 0 || tableList[1][0] === '未查询到数据') return { table: [], header, has: '0' };

        const table = [];
        let has = 0;
        for (let i = 1; i < tableList.length; i++) {
          const tem = [];
          columnNeed.forEach(idx => { tem.push(tableList[i][idx]); });
          if (tem[0]) { table.push(tem); }
          has += Number(tem[2]);
        }
        return { table, header, has: `${has}` };

      } catch (err) {
        return err;
      }
    }
    return { table: [], header, has: '0' };
  }

};
